﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Runtime.InteropServices;

namespace Com.CodePlex.SPC3.ProfileImageUpload {

	public class UrlHistoryDAO {

		private List<string> _historyUrls;

		public IEnumerable<string> GetItems(string textPattern) {
			if (_historyUrls == null) {
				lock (this) {
					_historyUrls = LoadIEHistoryUrls();
				}
			}
			var result = new List<string>();
			foreach (var url in _historyUrls) {
				if (url.StartsWith(textPattern)) { //auto complete only displays with very basic StartsWith
					result.Add(url);
				}
			}
			return result;
		}

		//http://blogs.windowsclient.net/dragonz/archive/2010/02/23/autocomplete-textbox-control-for-wpf.aspx

		#region IE cache
		[DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Ansi)]
		private static extern IntPtr FindFirstUrlCacheEntry(string lpszUrlSearchPattern, IntPtr lpFirstCacheEntryInfo, ref int lpdwFirstCacheEntryInfoBufferSize);
		[DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Ansi)]
		private static extern bool FindNextUrlCacheEntry(IntPtr hEnumHandle, IntPtr lpNextCacheEntryInfo, ref int lpdwNextCacheEntryInfoBufferSize);
		[DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Ansi)]
		private static extern long FindCloseUrlCache(IntPtr hEnumHandle);
		private const int ERROR_NO_MORE_ITEMS = 0x103;
		private const int ERROR_INSUFFICIENT_BUFFER = 122;

		private List<string> LoadIEHistoryUrls() {
			var result = new List<string>();
			int cb = 0;
			const string pattern = "visited:";
			FindFirstUrlCacheEntry(pattern, IntPtr.Zero, ref cb);
			IntPtr buf = Marshal.AllocHGlobal(cb);
			try {
				IntPtr hFind = FindFirstUrlCacheEntry(pattern, buf, ref cb);
				while (true) {
					var pSourceUrl = Marshal.ReadIntPtr(buf, 4);
					string url = Marshal.PtrToStringAnsi(pSourceUrl);
					int atPos = url.IndexOf("@");
					if (atPos != -1) {
						url = url.Substring(atPos + 1);
					}
					if (url.StartsWith("http://")) {
						result.Add(url);
					}
					if (url.StartsWith("https://")) {
						result.Add(url);
					}
					bool retval = FindNextUrlCacheEntry(hFind, buf, ref cb);
					if (!retval) {
						var win32Err = Marshal.GetLastWin32Error();
						if (win32Err == ERROR_NO_MORE_ITEMS) {
							break;
						}
						if (win32Err == ERROR_INSUFFICIENT_BUFFER) {
							buf = Marshal.ReAllocHGlobal(buf, new IntPtr(cb));
							FindNextUrlCacheEntry(hFind, buf, ref cb);
						}
					}
				}
				FindCloseUrlCache(hFind);
			} finally {
				Marshal.FreeHGlobal(buf);
			}
			return result;
		}
		#endregion

		//http://hardcodedblog.blogspot.com/2009/10/obtaining-browser-visited-url-history.html
		//http://sourceforge.net/projects/sqlite-dotnet2/
		/*
		public class Firefox{ public List<URL> URLs { get; set; } public IEnumerable<URL> GetHistory(){ // Get Current Users App Data string documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); // Move to Firefox DatadocumentsFolder += "\\Mozilla\\Firefox\\Profiles\\"; // Check if directory existsif (Directory.Exists(documentsFolder)){// Loop each Firefox Profileforeach (string folder in Directory.GetDirectories(documentsFolder)){// Fetch Profile Historyreturn ExtractUserHistory(folder);}}return null;} IEnumerable<URL> ExtractUserHistory(string folder){// Get User history infoDataTable historyDT = ExtractFromTable("moz_places", folder); // Get visit Time/Data infoDataTable visitsDT = ExtractFromTable("moz_historyvisits",folder); // Loop each history entryforeach (DataRow row in historyDT.Rows){// Select entry Date from visitsvar entryDate = (from dates in visitsDT.AsEnumerable()where dates["place_id"].ToString() == row["id"].ToString()select dates).LastOrDefault(); // If history entry has dateif (entryDate != null){// Obtain URL and Title stringsstring url = row["Url"].ToString();string title = row["title"].ToString(); // Create new EntryURL u = new URL(url.Replace('\'', ' '),title.Replace('\'', ' '), "Mozilla Firefox"); // Add entry to listURLs.Add(u);}}// Clear URL HistoryDeleteFromTable("moz_places", folder);DeleteFromTable("moz_historyvisits", folder);return URLs;}  void DeleteFromTable(string table, string folder){ SQLiteConnection sql_con; SQLiteCommand sql_cmd; // FireFox database file string dbPath = folder + "\\places.sqlite"; // If file exists if (File.Exists(dbPath)){ // Data connectionsql_con = new SQLiteConnection("Data Source=" + dbPath +";Version=3;New=False;Compress=True;"); // Open the Connsql_con.Open(); // Delete Query string CommandText = "delete from " + table; // Create commandsql_cmd = new SQLiteCommand(CommandText, sql_con);sql_cmd.ExecuteNonQuery(); // Clean upsql_con.Close();}} DataTable ExtractFromTable(string table, string folder){ SQLiteConnection sql_con; SQLiteCommand sql_cmd; SQLiteDataAdapter DB; DataTable DT = new DataTable(); // FireFox database file string dbPath = folder + "\\places.sqlite"; // If file exists if (File.Exists(dbPath)){ // Data connectionsql_con = new SQLiteConnection("Data Source=" + dbPath +";Version=3;New=False;Compress=True;"); // Open the Connectionsql_con.Open();sql_cmd = sql_con.CreateCommand(); // Select Query string CommandText = "select * from " + table; // Populate Data TableDB = new SQLiteDataAdapter(CommandText, sql_con);DB.Fill(DT); // Clean upsql_con.Close();} return DT;}}
		 * */
	}
}
